package com.kl.ccs;

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * Semaphore ，需要拿到许可才能执行，并可以选择公平和非公平模式
 */
@Slf4j
public class SemaphoreTest {

    /**
     * 假如现在有一段公路交通比较拥堵，那怎么办呢。此时，就需要警察叔叔出面，限制车的流量
     * 比如，现在有 20 辆车要通过这个地段， 警察叔叔规定同一时间，最多只能通过 5 辆车，其他车辆只能等待
     * 只有拿到许可的车辆可通过，等车辆通过之后，再归还许可，然后把它发给等待的车辆，获得许可的车辆再通行，依次类推
     */
    public static void main(String[] args) {

        int count = 20;
        ExecutorService executorService = Executors.newFixedThreadPool(count);

        // 指定最多只能有五个线程同时执行
        Semaphore semaphore = new Semaphore(5);

        Random random = new Random();
        for (int i = 0; i < count; i++) {
            final int no = i;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 获得许可，许可计数减一
                        semaphore.acquire();
                        log.info("{}:号车可通行", no);
                        // 模拟车辆通行耗时
                        Thread.sleep(random.nextInt(10000));
                        // 释放许可，许可计数加一
                        log.info("{}:号车已离开", no);
                        semaphore.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        executorService.shutdown();
    }
}
